package eu.drseus.qiwidrone.prototype.joystick;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import eu.drseus.qiwidrone.prototype.R;

public class Joystick {

	private View view;
	private Context context;
	
	private int totalWidthDIP = 164;
	private int totalHeightDIP = 164;
	
	private int originX = 0;
	private int originY = 0;
	
	private Paint radiusPaintOut;
	private Paint radiusPaintIn2;
	
	private Bitmap bitmapOverlayJoystickBackground;
	private Bitmap bitmapOverlayJoystickStick;
	
	private double userX = 0; //max: 100, min: -100
	private double userY = 0; //max: 100, min: -100
	
	private int paintUserXpx = 0;
	private int paintUserYpx = 0;

	private JoystickMovedListener moveListener;

	private JoystickClickedListener clickListener;

	private boolean touchMove;
	
	public Joystick(Context context, View view) {
		this.context = context;
		this.view = view;
		imageLoad();
		initColors();
	}
	
	private void imageLoad() {
        Bitmap overlayJoystickBackground = BitmapFactory.decodeResource(context.getResources(), R.drawable.joystick_background_164px);
        bitmapOverlayJoystickBackground = Bitmap.createScaledBitmap(overlayJoystickBackground, (int) (convertDIPtoPX(164)), (int) (convertDIPtoPX(164)), true);
        
        Bitmap overlayJoystickStick = BitmapFactory.decodeResource(context.getResources(), R.drawable.joystick_stick_80px);
        bitmapOverlayJoystickStick = Bitmap.createScaledBitmap(overlayJoystickStick, (int) (convertDIPtoPX(80)), (int) (convertDIPtoPX(80)), true);
	}

	private void initColors() {
        radiusPaintOut = new Paint(Paint.ANTI_ALIAS_FLAG);
        radiusPaintOut.setColor(Color.CYAN);
        radiusPaintOut.setStrokeWidth(convertDIPtoPX(2));
        radiusPaintOut.setStyle(Style.STROKE);
        radiusPaintOut.setAlpha(80);
        
        radiusPaintIn2 = new Paint(Paint.ANTI_ALIAS_FLAG);
        radiusPaintIn2.setColor(Color.CYAN);
        radiusPaintIn2.setStrokeWidth(convertDIPtoPX(2));
        radiusPaintIn2.setStyle(Style.FILL_AND_STROKE);
        radiusPaintIn2.setAlpha(230);
	}
	
    
    // =========================================
    // Public Methods 
    // =========================================

    public void setOnJostickMovedListener(JoystickMovedListener listener) {
            this.moveListener = listener;
    }
    
    public void setOnJostickClickedListener(JoystickClickedListener listener) {
            this.clickListener = listener;
    }	
	
	public int getWidth(){
		return (int) convertDIPtoPX(totalWidthDIP);
	}
	
	public int getHeight(){
		return (int) convertDIPtoPX(totalHeightDIP);
	}
	
	public void setJoystickCoordinates(double x, double y){
		userX = x;
		userY = y;

		x += 100.0;
		y += 100.0;
		
		paintUserXpx = (int) (x);
		paintUserYpx = (int) (y);
		
		
		 double dvW = (double)(getWidth())/200.0;
		 double dvH = (double)(getHeight())/200.0;
		
		paintUserXpx = (int) (dvW*x);
		paintUserYpx = (int) (dvH*y);
		
	}
	
	public double getX(){
		return userX;
	}
	
	public double getY(){
		return userY;
	}
	
	public void setOrigin(int x, int y){
		this.originX = x;
		this.originY = y;
	}
	

	public void draw(Canvas canvas){
		
		//Draw Background
		canvas.drawBitmap(bitmapOverlayJoystickBackground, originX, originY, null);
		
		int stickPositionX = (int) (originX
				//+ convertDIPtoPX(getWidth()) / 2
				- convertDIPtoPX(bitmapOverlayJoystickStick.getWidth() / 2)
				+ paintUserXpx);
		
		int stickPositionY = (int) (originY
				//+ convertDIPtoPX(getWidth()) / 2
				- convertDIPtoPX(bitmapOverlayJoystickStick.getHeight() / 2)
				+ paintUserYpx);
		
		Paint blackLine = new Paint(Paint.ANTI_ALIAS_FLAG);
		blackLine.setStrokeWidth(convertDIPtoPX(30));
		blackLine.setColor(Color.DKGRAY);
		
		Paint blackCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
		blackCircle.setColor(Color.DKGRAY);
		blackCircle.setStyle(Style.FILL);
		
		canvas.drawCircle(originX+getWidth()/2, originY+getHeight()/2, convertDIPtoPX(30/2), blackCircle);
		
		canvas.drawLine(originX+getWidth()/2, originY+getHeight()/2, stickPositionX+bitmapOverlayJoystickStick.getWidth()/2, stickPositionY+bitmapOverlayJoystickStick.getHeight()/2, blackLine);
		
		canvas.drawBitmap(
				bitmapOverlayJoystickStick,
				stickPositionX,
				stickPositionY,
				null);
	
		
		//Debug Stuff
		Paint paintFont = new Paint();
		paintFont.setColor(Color.BLACK);
		paintFont.setStyle(Paint.Style.FILL);
		paintFont.setAntiAlias(true);
		paintFont.setTextSize(10);
		canvas.drawText("X: "+((int)userX)+" Y: "+((int)userY), originX, originY-30, paintFont);
		
		
		canvas.save();
	}
	
    public boolean onTouchEvent(MotionEvent ev) {
    	
    	int tx = (int) (ev.getX()-originX);
    	int ty = (int) (ev.getY()-originY);
    	
    	if(tx < 0){
    		tx = 0;
    	}else if(tx > getWidth()){
    		tx = getWidth();
    	}
    	
    	if(ty < 0){
    		ty = 0;
    	}else if(ty > getHeight()){
    		ty = getHeight();
    	}
    	
		double dvWidth = (double)(getWidth())/200.0;
		double dvHeight = (double)(getHeight())/200.0;
		
		double txD = tx/dvWidth;
		double tyD = ty/dvHeight;
		
		txD -= 100;
		tyD -= 100;
		
		
    	
    	//Log.e("JS", "ACTION("+ev.getAction()+"): " + txD+" "+tyD);
    	
	    final int action = ev.getAction();
	    switch (action & MotionEvent.ACTION_MASK) {
		        case MotionEvent.ACTION_MOVE: {
		        	if(touchMove){
		        		setJoystickCoordinates(txD, tyD);
		        	}else{
						if (tx > 0 && tx <getWidth() && ty > 0 && ty < getHeight()) {
							setJoystickCoordinates(txD, tyD);
						}
		        	}
					break;
		        }       
		        case MotionEvent.ACTION_CANCEL: 
		        	break;
		        case MotionEvent.ACTION_UP: {
		            touchMove = false;
		        	returnHandleToCenter();
		            break;
		        }
		        case MotionEvent.ACTION_DOWN: {
                    if (tx > 0 && tx <getWidth() && ty > 0 && ty < getHeight()) {
                    		touchMove = true;
                    		setJoystickCoordinates(txD, tyD);
                    }
		            break;
		        }
		}    	
			
    	
    	return true;
    }
    
    private void returnHandleToCenter() {
        final int numberOfFrames = 5;
        final double intervalsX = (0 - userX) / numberOfFrames;
        final double intervalsY = (0 - userY) / numberOfFrames;

        for (int i = 0; i < numberOfFrames; i++) {
                final int j = i;
                view.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                        		userX += intervalsX;
                        		userY += intervalsY;
                                
                        		setJoystickCoordinates(userX, userY);
                                view.invalidate();
                                
                                if (moveListener != null && j == numberOfFrames - 1) {
                                        moveListener.onReturnedToCenter();
                                }
                        }
                }, i * 40);
        }

        if (moveListener != null) {
                moveListener.onReleased();
        }
	}

	// =========================================
    // Basic Functionality 
    // =========================================
	
	private boolean processMoveEvent(MotionEvent ev) {
		
		return true;
	}

	private float convertDIPtoPX(int dip){
		return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, context.getResources().getDisplayMetrics());
	}
}
